﻿using System;
using System.Text;
using System.Collections.Generic;
using System.Linq;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using BaffoHat.Core;

namespace BaffoHat.Core.Test
{
    [TestClass]
    public class GameTest
    {

        [TestMethod]
        public void Game_costructor()
        {
            Game game = new Game();

            Assert.AreEqual(game.Status, GameStatus.PlayersConfiguration);
            Assert.IsNull(game.GlassToBeDrunk);
            Assert.IsNotNull(game.Glasses);
            Assert.IsInstanceOfType(game.Dice, typeof(Dice));
        }

        [TestMethod]
        [ExpectedException(typeof(ArgumentNullException))]
        public void AddPlayer_null_paramiter()
        {
            Game game = new Game();
            game.AddPlayer(null);
        }

        [TestMethod]
        [ExpectedException(typeof(InvalidOperationException))]
        public void AddPlayer_wrong_status()
        {
            Game game = Workbench.GetGameReadyForRollDice();
            game.AddPlayer(new Player("gino"));
        }

        [TestMethod]
        public void AddPlayer()
        {
            Game game = new Game();
            game.AddPlayer(new Player("pippo"));

            Assert.AreEqual(game.Players.Count, 1);
            Assert.AreEqual(game.Players[0].Name, "pippo");
        }

        [TestMethod]
        [ExpectedException(typeof(InvalidOperationException))]
        public void StartGame_wrong_status()
        {
            Game game = Workbench.GetGameReadyForRollDice();
            game.StartGame();
        }

        [TestMethod]
        [ExpectedException(typeof(InvalidOperationException))]
        public void StartGame_without_players()
        {
            Game game = new Game();
            game.StartGame();
        }

        [TestMethod]
        public void StartGame()
        {
            Game game = Workbench.GetGameReadyForStart();
            game.StartGame();

            Assert.AreEqual(game.Status, GameStatus.WaitingDieRoll);
            Assert.AreEqual(game.PlayerTurn, game.Players[0]);
        }

        [TestMethod]
        [ExpectedException(typeof(InvalidOperationException))]
        public void RollDice_when_cant()
        {
            Game game = Workbench.GetGameReadyForRollDice();

            game.Dice = new GaffedDice();
            //giocatore uno riempie il bicchiere uno
            game.RollDice();
            //giocatore due fa ancora uno e deve bere il bicchiere
            game.RollDice();
            //viene sollevata una eccezzione perchè dovrebbe bere e non tirare
            game.RollDice();
        }


        [TestMethod]
        public void RollDice_when_glass_is_empty()
        {
            Game game = Workbench.GetGameReadyForRollDice();
            game.Dice = new GaffedDice();
            //giocatore uno riempie il bicchiere uno
            game.RollDice();

            Assert.AreEqual(game.Glasses[DiceFace.One].IsEmpty, false);
            Assert.IsNull(game.GlassToBeDrunk);
            Assert.AreEqual(game.Status, GameStatus.WaitingDieRoll);
        }

        [TestMethod]
        public void RollDice_when_glass_is_full()
        {
            Game game = Workbench.GetGameReadyForRollDice();
            game.Dice = new GaffedDice();
            //giocatore uno riempie il bicchiere uno
            game.RollDice();
            //giocatore due fa ancora uno e deve bere il bicchiere
            game.RollDice();

            Assert.AreEqual(game.Glasses[DiceFace.One].IsEmpty, false);
            Assert.AreEqual(game.GlassToBeDrunk, game.Glasses[DiceFace.One]);
            Assert.AreEqual(game.Status, GameStatus.WaitingDrinks);
        }

        [TestMethod]
        public void Drink_when_glass_is_full()
        {
            Game game = Workbench.GetGameReadyForRollDice();
            game.Dice = new GaffedDice();
            //giocatore uno riempie il bicchiere uno
            game.RollDice();
            //giocatore due fa ancora uno e deve bere il bicchiere
            game.RollDice();

            game.Drink();

            Assert.AreEqual(game.Glasses[DiceFace.One].IsEmpty, true);
            Assert.IsNull(game.GlassToBeDrunk);
            Assert.AreEqual(game.Status, GameStatus.WaitingDieRoll);
        }

        [TestMethod]
        [ExpectedException(typeof(InvalidOperationException))]
        public void Drink_when_cant()
        {
            Game game = Workbench.GetGameReadyForRollDice();
            game.Dice = new GaffedDice();

            game.Drink();
        }

        [TestMethod]
        public void DrinkWithoutHat_when_glass_is_full()
        {
            Game game = Workbench.GetGameReadyForRollDice();
            game.Dice = new GaffedDice();
            //giocatore uno riempie il bicchiere uno
            game.RollDice();
            //giocatore due fa ancora uno e deve bere il bicchiere
            game.RollDice();

            Player player = game.PlayerTurn;
            Int16 glassesDrink = game.PlayerTurn.GlassesDrink;

            game.DrinkWithoutHat();

            Assert.AreEqual(game.Glasses[DiceFace.One].IsEmpty, false);
            Assert.AreEqual(game.GlassToBeDrunk.DiceAssociation , DiceFace.One);
            Assert.AreEqual(game.Status, GameStatus.WaitingDrinks);
            Assert.AreEqual(game.PlayerTurn, player);
            Assert.AreEqual(game.PlayerTurn.GlassesDrink, glassesDrink + 1);
        }

        [TestMethod]
        [ExpectedException(typeof(InvalidOperationException))]
        public void DrinkWithoutHat_when_cant()
        {
            Game game = Workbench.GetGameReadyForRollDice();
            game.Dice = new GaffedDice();

            game.DrinkWithoutHat();
        }

        [TestMethod()]
        [DeploymentItem("BaffoHat.Core.dll")]
        public void ChangeTurn_test()
        {
            Game_Accessor game = new Game_Accessor();

            game.AddPlayer(new Player("pippo"));
            game.AddPlayer(new Player("pluto"));
            game.AddPlayer(new Player("paperino"));
            game.StartGame();

            Assert.AreEqual(game.PlayerTurn.Name , "pippo");

            game.ChangeTurn();

            Assert.AreEqual(game.PlayerTurn.Name, "pluto");

            game.ChangeTurn();

            Assert.AreEqual(game.PlayerTurn.Name, "paperino");

            game.ChangeTurn();

            Assert.AreEqual(game.PlayerTurn.Name, "pippo");
        }
    }
}
